package drds.data_propagate.parse.binlog_event_position_manager;

import drds.data_propagate.common.zookeeper.ZkClientx;
import drds.data_propagate.entry.position.BinLogEventPosition;
import drds.data_propagate.parse.exception.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class MixedBinLogEventPositionManager extends AbstractBinLogEventPositionManager {

    private final Logger logger = LoggerFactory.getLogger(MixedBinLogEventPositionManager.class);

    private final MemoryBinLogEventPositionManager memoryLogPositionManager;
    private final ZooKeeperBinLogEventPositionManager zooKeeperLogPositionManager;

    private final ExecutorService executor;

    public MixedBinLogEventPositionManager(ZkClientx zkClient) {
        if (zkClient == null) {
            throw new NullPointerException("null zkClient");
        }

        this.memoryLogPositionManager = new MemoryBinLogEventPositionManager();
        this.zooKeeperLogPositionManager = new ZooKeeperBinLogEventPositionManager(zkClient);

        this.executor = Executors.newFixedThreadPool(1);
    }

    @Override
    public void start() {
        super.start();

        if (!memoryLogPositionManager.isStart()) {
            memoryLogPositionManager.start();
        }

        if (!zooKeeperLogPositionManager.isStart()) {
            zooKeeperLogPositionManager.start();
        }
    }

    @Override
    public void stop() {
        super.stop();

        executor.shutdown();
        zooKeeperLogPositionManager.stop();
        memoryLogPositionManager.stop();
    }

    @Override
    public BinLogEventPosition getLatestBinLogEventPosition(String destination) {
        BinLogEventPosition binLogEventPosition = memoryLogPositionManager.getLatestBinLogEventPosition(destination);
        if (binLogEventPosition != null) {
            return binLogEventPosition;
        }
        binLogEventPosition = zooKeeperLogPositionManager.getLatestBinLogEventPosition(destination);
        // 这里保持和重构前的逻辑一致,重新添加到Memory中
        if (binLogEventPosition != null) {
            memoryLogPositionManager.persistBinLogEventPosition(destination, binLogEventPosition);
        }
        return binLogEventPosition;
    }

    @Override
    public void persistBinLogEventPosition(final String destination, final BinLogEventPosition binLogEventPosition) throws ParseException {
        memoryLogPositionManager.persistBinLogEventPosition(destination, binLogEventPosition);
        executor.submit(new Runnable() {

            public void run() {
                try {
                    zooKeeperLogPositionManager.persistBinLogEventPosition(destination, binLogEventPosition);
                } catch (Exception e) {
                    logger.error("ERROR # persist decode zookeeper has an error", e);
                }
            }
        });
    }
}
